(uiop:define-package #:ambrevar/syspack
  (:documentation "ASDF and package management helpers")
  (:use :common-lisp)
  (:import-from #:serapeum #:export-always))
(in-package #:ambrevar/syspack)

(export-always 'exported-symbols)
(declaim (ftype (function ((or symbol package))) exported-symbols))
(defun exported-symbols (package)
  "List exported symbols of PACKAGE."
  (let ((package (if (packagep package)
                     package
                     (find-package package)))
        (symbols))
    (do-external-symbols (s package symbols)
      (when (eq (symbol-package s) package)
        (push s symbols)))
    symbols))

(export-always 'system-depends-on)
(declaim (ftype (function (string)) system-depends-on))
(defun system-depends-on (system)
  "List SYSTEM dependencies, even if SYSTEM is an inferred system.
From: https://gitlab.common-lisp.net/asdf/asdf/issues/10#note_5018."
  (let (depends)
    (labels ((iter (openlist)
                   (if (null openlist) depends
                       ;; Is this a subsystem of SYSTEM?
                       (let ((find (search system (first openlist))))
                         (if (and find (zerop find))
                             (iter (append (asdf:system-depends-on (asdf:find-system (first openlist))) (rest openlist)))
                             ;; If not, it's a direct dependency: collect it.
                             (progn
                               (pushnew (first openlist) depends :test 'equalp)
                               (iter (rest openlist))))))))
      (iter (list system)))))
